package samples.stream;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.junit.Before;
import org.junit.Test;
import samples.lambda.Person2;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 这里用于测试数据聚合
 */
public class StatisticsTest {

    private List<Person2> list;
    private List<String> strings;

    // 初始化数据需要的
    @Before
    public void inti() {
        Person2 p1 = new Person2(13, "男", "张2");
        Person2 p2 = new Person2(2, "男", "张6");
        Person2 p3 = new Person2(4, "男", "张1");
        Person2 p4 = new Person2(6, "女", "张3");
        Person2 p5 = new Person2(1, "男", "张5");
        Person2 p6 = new Person2(10, "男", "张8");
        Person2 p7 = new Person2(3, "女", "张4");
        Person2 p8 = new Person2(31, "女", "张4");
        Person2 p9 = new Person2(21, "女", "张4");
        Person2 p10 = new Person2(19, "女", "张4");

        list = Lists.newArrayList(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
        strings = Lists.newArrayList("a1", "a2", "b1", "c2", "c1");
    }

    /**
     * count 8
     */
    @Test
    public void t1() {
        long count = list.stream()
                .filter(e -> e.getId() >= 3)
                .count();
        System.out.println(count);
    }

    /**
     * Stream 分组函数 使用
     * 女: 5男: 5
     */
    @Test
    public void t2() {
        Map<String, List<Person2>> collect = list.stream()
                .collect(Collectors.groupingBy(Person2::getSex));

        collect.forEach((age, p) -> System.out.format("%s: %s", age, p.size()));
    }

    /**
     * Stream平均函数使用
     * 11.0
     */
    @Test
    public void t3() {
        Double averageAge = list.stream()
                .collect(Collectors.averagingInt(p -> p.getId()));
        System.out.println(averageAge);
    }

    /**
     * Stream基本统计
     * ntSummaryStatistics{count=4, sum=76, min=12, average=19,000000, max=23}
     */
    @Test
    public void t4() {
        IntSummaryStatistics ageSummary =
                list.stream()
                        .collect(Collectors.summarizingInt(p -> p.getId()));
        System.out.println(ageSummary);
    }

    // 平均 2.45
    @Test
    public void t5() {
        Stream
                .of(new BigDecimal("1.2"), new BigDecimal("3.7"))
                .mapToDouble(BigDecimal::doubleValue)
                .average()
                .ifPresent(System.out::println);
    }


    /**
     * 基于初始数据，所有元素相加
     */
    @Test
    public void t6() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        int result = numbers
                .stream()
                .reduce(0, Integer::sum);
        System.out.println(result);
    }

    /**
     * 将某集合中的某一列，合并处理
     * 65
     */
    @Test
    public void t7() {
        List<User> users = Arrays.asList(
                new User("John", 30),
                new User("Julie", 35));
        int result = users.stream()
                .reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum);
        System.out.println(result);
    }

    /**
     * ,JohnJulie
     */
    @Test
    public void t8() {
        List<User> users = Arrays.asList(new User("John", 30), new User("Julie", 35));
        String reduce = users.stream()
                .reduce(",", (partialAgeResult, user) -> partialAgeResult + user.getName(), String::concat);
        System.out.println(reduce);
    }


    /**
     * 分组
     * {"MALE":[
     * 		"zc",
     * 		"zb",
     * 		"zm"
     * 	],"FEMALE":[
     * 		"as",
     * 		"zx",
     * 		"zv",
     * 		"zn"
     * 	]
     * }
     */
    @Test
    public void t9() {
        List<Person> roster = Arrays.asList(
                new Person("as", LocalDate.now(), Person.Sex.FEMALE, "Test@", 12),
                new Person("zx", LocalDate.now(), Person.Sex.FEMALE, "Test@", 12),
                new Person("zc", LocalDate.now(), Person.Sex.MALE, "Test@", 12),
                new Person("zv", LocalDate.now(), Person.Sex.FEMALE, "Test@", 12),
                new Person("zb", LocalDate.now(), Person.Sex.MALE, "Test@", 12),
                new Person("zn", LocalDate.now(), Person.Sex.FEMALE, "Test@", 12),
                new Person("zm", LocalDate.now(), Person.Sex.MALE, "Test@", 12)
        );

        Map<Person.Sex, List<String>> namesByGender =
                roster.stream()
                        .collect(
                                Collectors.groupingBy(
                                        Person::getGender,
                                        Collectors.mapping(
                                                Person::getName,
                                                Collectors.toList()))
                        );

        System.out.println(JSON.toJSONString(namesByGender, SerializerFeature.PrettyFormat));
    }











}
